import RDF

__all__ = ["collection"]

firstp = RDF.Uri("http://www.w3.org/1999/02/22-rdf-syntax-ns#first")
restp = RDF.Uri("http://www.w3.org/1999/02/22-rdf-syntax-ns#rest")
nil = RDF.Uri("http://www.w3.org/1999/02/22-rdf-syntax-ns#nil")

collection_test = """\
<?xml version="1.0" encoding="utf-8"?>
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
         xmlns:ex="http://www.example.com/">
  <rdf:Description about="http://www.example.com/">
    <ex:Example rdf:parseType="Collection">
      <ex:item rdf:value="first item" />
      <ex:item rdf:value="second item" />
      <ex:item rdf:value="third item" />
    </ex:Example>
  </rdf:Description>
</rdf:RDF>
"""

def collection(model, head):
	"""
	Iterates through through a collection in the given model starting
	with the "head" node. For each item in the collection yields a new
	in-memory model containing the statements for that item.

	This helper function is necessary because using rdf:parseType="Collection"
	results in a structure like a linked list in the RDF store. This
	function traverses the list.
	
	###
	### First initialize things and read in the test RDF document
	###
	>>> storage = RDF.Storage(storage_name="memory", name="collection_test",
	...                       options_string="")
	>>> model = RDF.Model(storage)
	>>> parser = RDF.Parser()
	>>> parser.parse_string_into_model(model, collection_test, "http://www.example.com/")
	True
	
	###
	### Find the pointer to the first item in the collection
	###
	>>> headp = RDF.Uri("http://www.example.com/Example")
	>>> s = RDF.Statement(None, headp, None)
	>>> for r in model.find_statements(s):
	...     head = r.object
	...
	
	###
	### Retrieve each of the items, and print out the results to test
	###
	>>> s = RDF.Statement(None, None, None)
	>>> for c in collection(model, head):
	...     print "--------"
	...     for r in c.find_statements(s):
	...         print r.predicate, r.object
	...
	--------
	[http://www.w3.org/1999/02/22-rdf-syntax-ns#type] [http://www.example.com/item]
	[http://www.w3.org/1999/02/22-rdf-syntax-ns#value] first item
	--------
	[http://www.w3.org/1999/02/22-rdf-syntax-ns#type] [http://www.example.com/item]
	[http://www.w3.org/1999/02/22-rdf-syntax-ns#value] second item
	--------
	[http://www.w3.org/1999/02/22-rdf-syntax-ns#type] [http://www.example.com/item]
	[http://www.w3.org/1999/02/22-rdf-syntax-ns#value] third item
	"""
	rest = head
	while True:
		s = RDF.Statement(rest, firstp, None)
		for r in model.find_statements(s):
			first = r.object
		s = RDF.Statement(first, None, None)
		storage = RDF.Storage(storage_name="memory", name=first.blank_identifier,
				      options_string="contexts='yes'")
		item = RDF.Model(storage)
		for r in model.find_statements(s):
			item.add_statement(r, head)
		yield item
		s = RDF.Statement(rest, restp, None)
		for r in model.find_statements(s):
			rest = r.object
			if rest.is_resource() and rest.uri == nil:
				rest = None
		if not rest:
			break

if __name__ == '__main__':
	import doctest
	doctest.testmod()
